#include "usart.h"

/*
PA9     ----    USART1_TX
PA10    ----    USART1_RX

*/

void USART_Init(void)
{
    // GPIOA时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN_Msk;
    // USART1时钟
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN_Msk;

    // GPIO 工作模式
    // PA9 复用推挽输出 CNF9:10 MODE9:11
    GPIOA->CRH |= GPIO_CRH_CNF9_1;
    GPIOA->CRH &= ~GPIO_CRH_CNF9_0;
    GPIOA->CRH |= GPIO_CRH_MODE9_Msk;
    // PA10 浮空输入 CNF10:01 MODE10:00
    GPIOA->CRH &= ~GPIO_CRH_CNF10_1;
    GPIOA->CRH |= GPIO_CRH_CNF10_0;
    GPIOA->CRH &= ~GPIO_CRH_MODE10_Msk;

    // 串口配置
    USART1->BRR = 0x271;
    USART1->CR1 |= (USART_CR1_UE_Msk | USART_CR1_TE_Msk | USART_CR1_RE_Msk);
    // 其他配置，设置数据帧格式
    // 8位数据，1个停止位，无校验位
    USART1->CR1 &= ~USART_CR1_M;
    USART1->CR1 &= ~USART_CR1_PCE;
    USART1->CR2 &= ~USART_CR2_STOP;
}

void USART_SendChar(uint8_t ch)
{
    // 判断状态 寄存器位 TXE 是否为 1
    while (!(USART1->SR & USART_SR_TXE_Msk))
        ;
    // 写入数据
    USART1->DR = ch;
}
uint8_t USART_ReceiveChar(void)
{
    // 判断状态 寄存器位 接受缓冲区(RXNE) 是否为 1
    while (!(USART1->SR & USART_SR_RXNE_Msk))
        ;
    // 读取数据
    return USART1->DR;
}

// 发送字符串
void USART_SendString(uint8_t *str, uint8_t size)
{
    for (uint8_t i = 0; i < size; i++)
    {
        USART_SendChar(str[i]);
    }
}
// 接受字符串
void USART_ReceiveString(uint8_t buffer[], uint8_t *size)
{
    uint8_t i = 0;
    while (1)
    {
        while (!(USART1->SR & USART_SR_RXNE_Msk))
            ; // 等待接收数据
        {
            while (!(USART1->SR & USART_SR_IDLE_Msk)) // 空闲帧
            {
                *size = i;
                return;
            }
        }
        buffer[i] = USART1->DR;
        i++;
    }
}

// 重定向 printf 到串口
int _write(int fd, char *ch, int len)
{
    USART_SendString((uint8_t *)ch, len);
    //   HAL_UART_Transmit(&huart1, (uint8_t*)ch, len, 0xFFFF);
    return len;
}